package com.aizuda.snailjob.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.aizuda.snailjob.config.SourceDBConfig;
import com.aizuda.snailjob.config.TargetDBConfig;
import com.aizuda.snailjob.core.Collector;
import com.aizuda.snailjob.core.DataMigrationTool;
import com.aizuda.snailjob.vo.MigrationVO;
import com.aizuda.snailjob.vo.NamespaceVO;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Map;

@Service
public class DataMigrationService {

    /**
     * 迁移工具
     */
    @Async
    public void migration(MigrationVO migrationVO) {

        DataSource source = initSourceDataSource(migrationVO.getSourceDB());
        DataSource target = initTargetDataSource(migrationVO.getTargetDB());

        try {
            NamespaceVO namespace = migrationVO.getNamespace();
            if (StrUtil.isBlank(namespace.getId())) {
                namespace.setId(IdUtil.nanoId(32));
            }

            Integer totalBucket = migrationVO.getTotalBucket();
            if (totalBucket == null || totalBucket <= 0) {
                totalBucket = 128;
            }

            String namespaceId = namespace.getId();
            String name = namespace.getName();

            // 生成命名空间
            DataMigrationTool.migrationNamespace(target, name, namespaceId);

            // 迁移组
            Map<Long, String> map = DataMigrationTool.migrationGroup(source, target, namespaceId);

            // 迁移job
            DataMigrationTool.migrationJob(source, target, map, namespaceId, totalBucket);

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    private static DataSource initSourceDataSource(SourceDBConfig source) {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(source.getUrl());
        config.setPassword(source.getPassword());
        config.setUsername(source.getUser());
        return new HikariDataSource(config);
    }

    private static DataSource initTargetDataSource(TargetDBConfig target) {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(target.getUrl());
        config.setPassword(target.getPassword());
        config.setUsername(target.getUser());
        return new HikariDataSource(config);
    }

    /**
     * 迁移进度
     *
     * @return
     */
    public Collector migrationProgress() {
        return DataMigrationTool.COLLECTOR;
    }
}
